package com.t.bricks.bussiness.dao.bridge.impl;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.t.bricks.bussiness.dao.bridge.BridgeDao;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.function.json.JacksonShell;
import com.t.bricks.utils.function.url.URLUtil;

/**
 * 桥接数据操作
 * @author huangxinbian
 */
@Component
public class BridgeDaoImpl implements BridgeDao {
	
	/**
	 * Cloud注册中心地址(分布式时使用)
	 */
	@Value("${cloud.center.site:}")
	private String cloudCenterUrl;
	
	/**
	 * Cloud注册中心用户密码(分布式时使用)
	 */
	@Value("${cloud.center.password:}")
	private String cloudCenterPass;
	
	/**
	 * 项目所在域名
	 */
	@Value("${server.domain.name:}")
	private String domainName;
	
	/**
	 * post请求
	 * @param serverName 服务名
	 * @param url 请求的相对路径
	 * @param parameters 请求参数
	 * @param resultType 返回类型
	 * @param isResultList 返沪类型是否list
	 * @return
	 */
	@Override
	public MsgEmity post(String serverName, String url, Map<String, Object> parameters,
			Class<?> resultType, Boolean isResultList) {
		Map<String, String> hearMap = getHearInfo();//取请求头参数
		return this.post(serverName, url, parameters, resultType, isResultList, hearMap);
	}
	
	/**
	 * GET请求
	 * @param serverName 服务名
	 * @param url 请求的相对路径
	 * @param resultType 返回类型
	 * @param isResultList 返沪类型是否list
	 * @return
	 */
	@Override
	public MsgEmity get(String serverName, String url, Class<?> resultType, Boolean isResultList) {
		Map<String, String> hearMap = getHearInfo();//取请求头参数
		return this.get(serverName, url, resultType, isResultList, hearMap);
	}
	
	/**
	 * post请求
	 * @param serverName 服务名
	 * @param url 请求的相对路径
	 * @param parameters 请求参数
	 * @param resultType 返回类型
	 * @param isResultList 返沪类型是否list
	 * @param hearMap 自定义请求头
	 * @return
	 */
	@Override
	public MsgEmity post(String serverName, String url, Map<String, Object> parameters,
			Class<?> resultType, Boolean isResultList, Map<String, String> hearMap) {
		MsgEmity me = findServerSite(serverName);
		if (!me.isSuccess()) {
			return me;
		}
		
		int iSize = null == parameters ? 0 : parameters.size();
		iSize = iSize + (null == hearMap ? 0 : hearMap.size());
		Map<String, Object> map = new HashMap<>(iSize);
		if (null != parameters && parameters.size() > 0) {
			map.putAll(parameters);
		}
		
		if (null != hearMap && hearMap.size() > 0) {
			map.putAll(hearMap);
		}
		
		url = String.format("%s%s", (String)me.getData(), url);
		//me = URLUtil.post(url, parameters, hearMap);
		me = URLUtil.post(url, map, null);
		if (!me.isSuccess()) {
			return me;
		}
		
		if (null == me.getData()) {
			return null;
		}
		
		if (null == resultType) {
			return me;
		}
		
		if (String.class.equals(resultType)) {
			return me;
		}
		
		if (isResultList) {
			Object result = JacksonShell.toJavaList(me.getData(), resultType);
			return me.setData(result);
		}
		
		Object result = JacksonShell.toJavaObject((String)me.getData(), resultType);
		
		return me.setData(result);
	}
	
	/**
	 * GET请求
	 * @param serverName 服务名
	 * @param url 请求的相对路径
	 * @param resultType 返回类型
	 * @param isResultList 返沪类型是否list
	 * @param hearMap 自定义请求头
	 * @return
	 */
	@Override
	public MsgEmity get(String serverName, String url, Class<?> resultType,
			Boolean isResultList, Map<String, String> hearMap) {
		MsgEmity me = findServerSite(serverName);
		if (!me.isSuccess()) {
			return me;
		}
		
		url = String.format("%s%s", (String)me.getData(), url).replaceAll("//",  "/");
		me = URLUtil.get(url, hearMap);
		if (!me.isSuccess()) {
			return me;
		}
		
		if (null == me.getData()) {
			return null;
		}
		
		if (null == resultType) {
			return me;
		}
		
		if (String.class.equals(resultType)) {
			return me;
		}
		
		if (isResultList) {
			Object result = JacksonShell.toJavaList(me.getData(), resultType);
			return me.setData(result);
		}
		
		Object result = JacksonShell.toJavaObject((String)me.getData(), resultType);
				
		return me.setData(result);
	}

	/**
	 * 访问注册中心,获取服务地址
	 * @param serverName
	 * @param cloudCenterUrl
	 * @return
	 */
	private MsgEmity findServerSite(String serverName) {
		if (null == cloudCenterUrl || "".equals(cloudCenterUrl.trim())) {
			return MsgEmity.err(7101, "项目未配置注册中心地址,配置项'cloud.center.site'");
		}
		
		String url = String.format("http://%s/find/name?sName=%s&key=%s", cloudCenterUrl, serverName, cloudCenterPass).replace("http://http://", "http://");
		MsgEmity me = URLUtil.get(url);
		if (!me.isSuccess()) {
			return me;
		}
		
		MsgEmity result = JacksonShell.toJavaObject(me.getData(), MsgEmity.class);
		if (null == result) {
			return MsgEmity.err(7102, "访问注册中心失败,未能获取预期信息");
		}
		
		if (!result.isSuccess()) {
			if (result.getData() instanceof Integer) {
				return result.setData((Integer)result.getData() + 200);
			}
			
			return result;
		}
		
		Map<String, Object> map = JacksonShell.toJavaObject(result.getData(), Map.class);//{"success":true,"msg":"找到数据","data":"{\"sSign\":\"TBaseSystemServer\",\"serverPort\":\"9002\",\"serverIp\":\"192.168.56.1\"}"}
		if (!map.containsKey("domainName") || null == map.get("domainName") || "".equals(map.get("domainName"))) {//没有启用域名
			String str = String.format("http://%s:%s", map.get("serverIp"), map.get("serverPort"));
			return result.setData(str);
		}
		
		if (map.containsKey("domainName") && !"".equals(map.get("domainName")) && domainName.equals(map.get("domainName"))) {//启用域名,但域名与本程序一致,则属于同一个服务器或同一个局域网内
			String str = String.format("http://%s:%s", map.get("serverIp"), map.get("serverPort"));//通过ip和端口访问
			return result.setData(str);
		}
		
		if (!map.containsKey("domainPort") || null == map.get("domainPort") || "".equals(map.get("domainPort"))) {//启用域名但没有使用端口,则端口为80
			String str = String.format("http://%s", map.get("domainName"));
			return result.setData(str);
		}
		
		//启用域名且使用指定端口
		String str = String.format("http://%s:%s", map.get("domainName"), map.get("domainPort"));
		
		return result.setData(str);
	}
	
	/**
	 * 取请求头信息
	 * @return
	 */
	private static Map<String, String> getHearInfo() {
		HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();

		Enumeration<String> er = request.getHeaderNames();// 获取请求头的所有name值
		
		Map<String, String> map = new HashMap<>();
		while (er.hasMoreElements()) {
			String name = (String) er.nextElement();
			map.put(name, request.getHeader(name));
		}

		return map;
	}
	
}
